﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;

namespace Pigs.Enemies
{
    class Bunny_Pig : pigs.Pig
    {
        //Used for determining where to co
        private Vector2 destination;
        private Vector2 start;
        public Random rand;
        public int count;
        public int spawn;
        public float vert;
        public float numPlayers;
        public bool up;
        public Vector2 memory;
        public int aiTimer;

        // Animation variables
        int frameCount = 0; // Current frame
        int frameSkipX = 60; // Width of a frame
        int animationCount; // How many ticks since the last frame change.
        int animationMax; // How many ticks to change frame after. 
        Rectangle source;

        /// <summary>
        /// make the new pig
        /// </summary>
        /// <param name="texture">texture to use</param>
        /// <param name="position">where should the pig start out</param>
        public Bunny_Pig(Texture2D texture, Vector2 position, float numbPlayers)
            : base(texture, position)
        {
            START_HEALTH = 1;
            START_DAMAGE = 5;
            START_SPEED = 0.5f;
            VALUE = 15;

            this.shouldEatSlop = true;
            this.position = position;
            this.active = true; // We initialize the enemy to be active so it will be update in the game

            this.numPlayers = numbPlayers;
            if (numPlayers == 1) { this.health = START_HEALTH; }
            else if (numPlayers > 1 && numPlayers < 3) { this.health = START_HEALTH * 2; }
            else { this.health = this.START_HEALTH * 3; }
            
            this.damage = START_DAMAGE * (int)((numPlayers / 2) + 0.5f);
            this.speed = START_SPEED;
            this.vertSpeed = 0;
            this.vert = 0;
            this.value = VALUE;
            this.effect = SpriteEffects.None;
            this.ID = "bunny";
            this.start = new Vector2(this.position.X, this.position.Y);
            this.rand = new Random();
            
            //Choose a random vector to move to when a bunny spawns
            this.destination = new Vector2(this.position.X - 20, this.position.Y + rand.Next(-50,50));
            this.count = 5;
            
            //Set the leader buff to false
            this.lead = false;
            this.buff = false;
            this.up = false;
            
            //Cut the initial spawn time based on the amount of players
            float tmp = (numPlayers / 2) + 0.5f;
            if (tmp == 0) { tmp = 1; }
            else { this.spawn = 250 / (int)tmp; }
            this.memory = new Vector2(0, 0);
            this.memory.X = (this.destination.X - this.start.X) / 10;
            this.memory.Y = (this.destination.Y - this.start.Y) / 10;
            this.aiTimer = 1;
            this.escaped = false;
            this.hitByFlame = false;
            this.ghost = false;

            // Start with frame 1 of image array
            this.frameCount = 1;
            this.animationCount = 0;
            this.animationMax = 1;

            this.source = new Rectangle(this.frameSkipX * this.frameCount, 0, this.frameSkipX, this.texture.Height);

            rectangle = new Rectangle((int)position.X, (int)position.Y, source.Width, source.Height);

            //get the color data for the texture
            colorMap = new Color[source.Width * source.Height];
            this.texture.GetData(0, source, colorMap, 0, source.Width * source.Height);
        }


        public bool doAI(List<pigs.Scenery> obstacles, List<pigs.Pig> pigs, bool leadPig, pigs.Pig p)
        {
            if (aiTimer > 0)
            {
                this.position += this.memory;
                aiTimer -= 1;
                return false;
            }
            else
            {
                aiTimer = 0;
                // With a leader buff
                // Double a bunny pig's damage and current health
                if (this.lead && !this.buff)
                {
                    this.health *= 2;
                    this.damage *= 2;
                    this.buff = true;
                }
                if (health <= 0)
                {
                    // By setting the Active flag to false, the game will remove this object from the 
                    // active game list
                    active = false;
                }
                avoidSuicide(pigs, obstacles);
                // For moving to a bunny pigs destination (hop)
                if (count > 0 && !leadPig)
                {
                    this.memory.X = (this.destination.X - this.start.X) / 10;
                    this.memory.Y = (this.destination.Y - this.start.Y) / 10;
                    this.position.X += this.memory.X;
                    this.position.Y += this.memory.Y;
                    this.count -= 1;
                }
                else
                {
                    // If the pig isn't moving, decrement the spawn timer
                    this.spawn -= 1;
                    if (this.spawn < 1)
                    {
                        // Set the spawn timer based on the number of players
                        // If a bunny pig had recieved a leader buff, cut the spawn time in half.
                        if (!leadPig)
                        {
                            if (numPlayers == 1)
                            {
                                this.spawn = rand.Next(300, 400);
                            }
                            else if (numPlayers > 2 && numPlayers < 5)
                            {
                                this.spawn = rand.Next(200, 300);
                            }
                            else
                            {
                                this.spawn = rand.Next(100, 200);
                            }
                            if (this.buff)
                            {
                                this.spawn = this.spawn / 2;
                            }

                            // If the pig just spawned, set the move destination and timer
                            this.count = 10;
                            this.start = this.position;
                            this.destination = this.position;
                            this.destination.X += this.rand.Next(-100, 100);
                            this.destination.Y += this.rand.Next(-100, 100);
                            // Ensure that the destination isn't a mountain
                            while (((this.ObstacleMove(obstacles, "avoid", this.destination) != "none") ||
                                       this.destination.Y < 10)
                                       && this.count != 0)
                            {
                                this.destination.X += this.rand.Next(-100, 100);
                                this.destination.Y += this.rand.Next(-100, 100);
                                count -= 1;
                            }
                            return true;
                        }
                    }
                    if (leadPig)
                    {
                        Vector2 pigCenter = this.center();
                        Vector2 leadCenter = p.center();
                        float xDist = pigCenter.X - leadCenter.X;
                        float yDist = pigCenter.Y - leadCenter.Y;

                        Vector2 direction = new Vector2(xDist / (Math.Abs(xDist) + Math.Abs(yDist)), yDist / (Math.Abs(xDist) + Math.Abs(yDist)));
                        float angle = (float)(Math.Atan2(direction.Y, direction.X));
                        if (Vector2.Distance(pigCenter, leadCenter) > 125)
                        {
                            this.memory.X = (float)Math.Cos(angle) * -2;
                            this.memory.Y = (float)Math.Sin(angle) * -2;
                            this.position.X += this.memory.X;
                            this.position.Y += this.memory.Y;
                        }
                        else if (Vector2.Distance(pigCenter, leadCenter) < 75)
                        {
                            this.memory.X = (float)Math.Cos(angle) * 2;
                            this.memory.Y = (float)Math.Sin(angle) * 2;
                            this.position.X += this.memory.X;
                            this.position.Y += this.memory.Y;
                        }
                        else
                        {
                            angle -= (float)Math.PI / 2;
                            this.memory.X = (float)Math.Cos(angle) * 5;
                            this.memory.Y = (float)Math.Sin(angle) * 5;
                            this.position.X += this.memory.X;
                            this.position.Y += this.memory.Y;
                        }


                        if (this.spawn < 1)
                        {
                            // Set the spawn timer based on the number of players
                            // If a bunny pig had recieved a leader buff, cut the spawn time in half.
                            if (numPlayers == 1)
                            {
                                this.spawn = rand.Next(300, 400) / 2;
                            }
                            else if (numPlayers > 2 && numPlayers < 5)
                            {
                                this.spawn = rand.Next(200, 300) / 2;
                            }
                            else
                            {
                                this.spawn = rand.Next(100, 200) / 2;
                            }
                            return true;
                        }
                        return false;
                    }
                }

                this.memory.X = this.speed;
                this.memory.Y = this.vertSpeed;
                this.position.X -= this.memory.X;
                this.position.Y += this.memory.Y;
                return false;
            }
        }

        public override bool bunnyUpdate(GameTime gameTime, List<pigs.Scenery> obstacles, List<pigs.Pig> pigs, bool leadPig, pigs.Pig p)
        {
            if (this.shouldGhost && this.color.A > 70)
            {
                this.color.A--;
                this.color.A--;
                this.color.A--;
            }


            // breed is used to signal level to generate a new pig 
            bool breed = false;
            // Standared avoid scenery call, if a pig isn't avoiding scenery do its AI
            if (leadPig)
            {
                breed = this.doAI(obstacles, pigs, leadPig, p);
            }
            else if (!this.avoidScenery(obstacles))
            {
                breed = this.doAI(obstacles, pigs, leadPig, p);
            }
            else
            {
                this.position.X -= 0.2f;
            }
            rectangle = new Rectangle((int)this.position.X, (int)this.position.Y, source.Width, source.Height);
            UpdateAnimation();
            return breed;
        }

        // Perform the animation updates on the image
        public void UpdateAnimation()
        {
            this.animationCount += 1;
            if (this.animationCount > this.animationMax)
            {
                this.animationCount = 0;
                this.frameCount += 1;
                if (this.frameCount == 5)
                {
                    this.frameCount = 0;
                }
            }
        }

        //Draw the updated texture image
        public override void Draw(SpriteBatch spriteBatch)
        {
            // Update the source rectangle, based on where in the animation we are.  
            this.source.X = this.frameSkipX * this.frameCount;

            spriteBatch.Draw(texture, position, this.source, color, 0, new Vector2(0, 0), 1f, SpriteEffects.None, 0f);
        }
    }
}
